/*
*  Copyright 2019-2023 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package me.zhengjie.modules.shop.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import me.zhengjie.exception.BizException;
import me.zhengjie.modules.pay.domain.dto.ProductDTO;
import me.zhengjie.modules.shop.domain.Product;
import me.zhengjie.modules.shop.domain.ProductKind;
import me.zhengjie.modules.shop.domain.ProductModule;
import me.zhengjie.modules.shop.domain.dto.BackProductDTO;
import me.zhengjie.modules.shop.domain.req.ProductStatusReq;
import me.zhengjie.modules.shop.domain.resp.ProductResp;
import me.zhengjie.modules.shop.domain.vo.ProductModuleQueryCriteria;
import me.zhengjie.modules.shop.mapper.ProductKindMapper;
import me.zhengjie.modules.shop.mapper.ProductModuleMapper;
import me.zhengjie.utils.FileUtil;
import lombok.RequiredArgsConstructor;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import me.zhengjie.modules.shop.service.ProductService;
import me.zhengjie.modules.shop.domain.vo.ProductQueryCriteria;
import me.zhengjie.modules.shop.mapper.ProductMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import me.zhengjie.utils.PageUtil;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.io.IOException;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse;

import me.zhengjie.utils.PageResult;

import static me.zhengjie.modules.biz.domain.enums.ErrorCode.*;
import static me.zhengjie.modules.pay.enums.StatusEnum.PRODUCT_OFF;
import static me.zhengjie.modules.pay.enums.StatusEnum.PRODUCT_ON;

/**
* @description 服务实现
* @author yiwei.he
* @date 2024-04-11
**/
@Service
@RequiredArgsConstructor
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {

    private final ProductMapper productMapper;

    private final ProductKindMapper productKindMapper;

    private final ProductModuleMapper productModuleMapper;

    @Override
    public PageResult<BackProductDTO> queryAll(ProductQueryCriteria criteria, Page<Object> page){
        IPage<BackProductDTO> all = productMapper.adminList(criteria, page);
        List<BackProductDTO> records = all.getRecords();
        records.forEach(record ->{
            // 存放模块id
            List<Long> list = new ArrayList<>();
            list.add(record.getTopModuleId());
            list.add(record.getModuleId());
            record.setIds(list);
        });
        all.setRecords(records);
        return PageUtil.toPage(all);
    }

    @Override
    public List<Product> queryAll(ProductQueryCriteria criteria){
        return productMapper.findAll(criteria);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Product resources) throws BizException {
        if(checkProduct(resources)){
            // 设置创建商品时间
            resources.setCreateTime(LocalDateTime.now());
            save(resources);
        }else{
            // 商品的名称不能重复，否则会对添加商品种类时带来困扰【商品不唯一，管理员不知道自己加的是那一个类别】
            throw new BizException(PRODUCT_ALREADY_EXIST.getCode(),PRODUCT_ALREADY_EXIST.getMessage());
        }
    }

    private boolean checkProduct(Product resources) {
        // 查看商品是否已添加过了
        Product product = productMapper.selectOne(new QueryWrapper<Product>()
                .eq("name", resources.getName())
                .eq(resources.getResources() != null,"store_id", resources.getStoreId())
        );
        return product == null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Product resources) throws BizException {
        // todo 修改暂时不做校验，后续根据需要进行补充判断
        Product product = getById(resources.getId());
        product.copy(resources);
        saveOrUpdate(product);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(List<Long> ids) {
        removeBatchByIds(ids);
    }

    @Override
    public void download(List<Product> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (Product product : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("店铺id【平台上架的商品默认为0】", product.getStoreId());
            map.put("商品大类id", product.getModuleId());
            map.put("商品名称", product.getName());
            map.put("商品封面图", product.getCover());
            map.put("商品简介", product.getIntro());
            map.put("总销量", product.getSold());
            map.put("上下架【0：下架 1：上架】", product.getStatus());
            map.put("图片资源【商品的图片】", product.getResources());
            map.put("创建时间", product.getCreateTime());
            map.put("描述", product.getRemark());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    @Transactional
    public void onOrOff(ProductStatusReq req) {
        LocalDateTime now = LocalDateTime.now();
        // 转换商品的状态，如果是上架状态，修改为下架，如果是下架的状态，改为上架
        Integer convertStatus = req.getStatus() == PRODUCT_ON.getCode() ? PRODUCT_OFF.getCode() : PRODUCT_ON.getCode();
        for (Long id : req.getIds()) {
            Product product = productMapper.selectById(id);
            if (product != null) {
                product.setCreateTime(now);
                product.setStatus(convertStatus);
                productMapper.update(product, new UpdateWrapper<Product>().eq("id", id));
            }
        }
    }

    /**
     * 小程序查看商品详情
     * @param id 商品ID
     * @return 商品详情响应对象
     */
    @Override
    public ProductResp getProduct(Long id) throws BizException {
        ProductResp resp = new ProductResp();
        // 1.查看商品基础属性
        Product product = productMapper.selectById(id);
        if (product == null) {
            throw new BizException(BODY_NOTNULL.getCode(), BODY_NOTNULL.getMessage());
        }
        // 2.查看商品分类
        List<ProductKind> kinds = productKindMapper.selectList(new QueryWrapper<ProductKind>().eq("p_id", id));
        int totalStock = 0;
        BigDecimal minPrice = BigDecimal.valueOf(Double.MAX_VALUE);
        if (!kinds.isEmpty()) {
            totalStock = kinds.stream().mapToInt(ProductKind::getStock).sum();
            minPrice = kinds.stream().map(ProductKind::getPrice).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        }else {
            minPrice = BigDecimal.ZERO;
        }
        // 4.封装商品详情
        resp.setMinPrice(minPrice);
        resp.setTotalStock(totalStock);
        BeanUtil.copyProperties(product, resp);
        resp.setKinds(kinds);
        return resp;
    }

    @Override
    public PageResult<ProductResp> getProductList(ProductQueryCriteria criteria, Page<Object> page) throws BizException {
        if(criteria.getModuleId() == null){
            throw new BizException(MODULE_ID_NOT_NULL.getCode(),MODULE_ID_NOT_NULL.getMessage() );
        }
        Long moduleId = criteria.getModuleId();
        // 查询商品模块,如果传的是父级模块，则子集的商品也需要展示
        List<Long> moduleIds = productModuleMapper.findAll(new ProductModuleQueryCriteria()).stream()
                .filter(module -> Objects.equals(module.getParentId(), moduleId) || Objects.equals(module.getId(), moduleId))
                .map(ProductModule::getId)
                .collect(Collectors.toList());
        // 获取该模块下的商品列表
        List<Product> productList = productMapper.selectList(new QueryWrapper<Product>().in("module_id", moduleIds));
        // 获取已上架的商品
        List<Product> products = productList.stream().filter(product -> product.getStatus() == 1).collect(Collectors.toList());
        ArrayList<ProductResp> productResps = new ArrayList<>();
        for (Product product : products) {
            ProductResp resp = new ProductResp();
            // 2.查看商品分类
            List<ProductKind> kinds = productKindMapper.selectList(new QueryWrapper<ProductKind>().eq("p_id", product.getId()));
            int totalSold = kinds.stream().mapToInt(ProductKind::getSold).sum();
            int totalStock = 0;
            BigDecimal minPrice = BigDecimal.valueOf(Double.MAX_VALUE);
            if (!kinds.isEmpty()) {
                totalStock = kinds.stream().mapToInt(ProductKind::getStock).sum();
                minPrice = kinds.stream().map(ProductKind::getPrice).min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
            }else {
                minPrice = BigDecimal.ZERO;
            }
            // 4.封装商品详情
            resp.setMinPrice(minPrice);
            resp.setTotalStock(totalStock);
            resp.setSold(totalSold);
            BeanUtil.copyProperties(product, resp);
            productResps.add(resp);
        }
        return PageUtil.toPage(productResps);
    }

}